package com.whfc.mach.manager.warn;

import com.whfc.base.enums.AppModuleType;
import com.whfc.base.param.AlarmMessageParam;
import com.whfc.base.service.WarnConfigService;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.JSONUtil;
import com.whfc.entity.dto.msg.AppMsgToUserDTO;
import com.whfc.entity.dto.msg.PushMsgDTO;
import com.whfc.mach.dao.AppMachWarnRuleChannelMapper;
import com.whfc.mach.dao.AppMachWarnRuleTimeMapper;
import com.whfc.mach.dao.AppMachWarnRuleUserMapper;
import com.whfc.mach.dto.warn.AppWarnTimeDTO;
import com.whfc.mach.dto.warn.MachWarnCheckDTO;
import com.whfc.mach.dto.warn.MachWarnRuleDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @author sun_guodong
 * @description
 * @date 2021-01-09
 */
@Service
public abstract class AbstractWarnManager implements AppWarnManager {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private AppMachWarnRuleTimeMapper appMachWarnRuleTimeMapper;

    @Autowired
    private AppMachWarnRuleChannelMapper appMachWarnRuleChannelMapper;

    @Autowired
    private AppMachWarnRuleUserMapper appMachWarnRuleUserMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @DubboReference(interfaceClass = WarnConfigService.class, version = "1.0.0")
    private WarnConfigService warnConfigService;

    @Override
    public void checkWarn(MachWarnCheckDTO machWarnCheckDTO, MachWarnRuleDTO machWarnRuleDTO) {
        logger.info("检测报警规则,ruleType:{}", machWarnRuleDTO.getRuleType());

        // 检测是否在报警时间段内
        Date time = machWarnCheckDTO.getTriggerTime();
        Integer ruleId = machWarnRuleDTO.getRuleId();
        boolean checkTime = this.checkTime(ruleId, time);
        if (!checkTime) {
            return;
        }

        // 检测是否触发报警值
        boolean isMeetRuleValue = this.checkValue(machWarnCheckDTO, machWarnRuleDTO);
        if (!isMeetRuleValue) {
            return;
        }

        // 检测报警频率
        Integer deptId = machWarnCheckDTO.getDeptId();
        String objectId = String.valueOf(machWarnCheckDTO.getMachId());
        Integer ruleType = machWarnRuleDTO.getRuleType();
        boolean isMeetAlarmFrequency = warnConfigService.checkAlarmFrequency(deptId, AppModuleType.MACH.value(), ruleType, objectId, time);
        if (!isMeetAlarmFrequency) {
            return;
        }

        // 生成报警记录
        AlarmMessageParam alarmMessageParam = this.generateWarnRecord(machWarnCheckDTO, machWarnRuleDTO);

        // 生成报警消息
        this.generateMessage(alarmMessageParam);
    }

    /**
     * 检测是否触发报警值
     *
     * @param machWarnCheckDTO
     * @param machWarnRuleDTO
     * @return
     */
    public abstract boolean checkValue(MachWarnCheckDTO machWarnCheckDTO, MachWarnRuleDTO machWarnRuleDTO);

    /**
     * 生成报警
     *
     * @param machWarnCheckDTO
     * @param machWarnRuleDTO
     * @return
     */
    public abstract AlarmMessageParam generateWarnRecord(MachWarnCheckDTO machWarnCheckDTO, MachWarnRuleDTO machWarnRuleDTO);

    /**
     * 检测是否在报警时间段内
     *
     * @param ruleId
     * @param time
     * @return
     */
    private boolean checkTime(Integer ruleId, Date time) {
        // 增加时间浮动
        Random r = new Random();
        int intervalMinutes = r.nextInt(60);
        boolean flag = false;
        List<AppWarnTimeDTO> timeList = appMachWarnRuleTimeMapper.selectByRuleId(ruleId);
        for (AppWarnTimeDTO timeDTO : timeList) {
            Date startTime = DateUtil.addMinutes(timeDTO.getStartTime(), intervalMinutes);
            Date endTime = timeDTO.getEndTime();
            if (endTime.after(DateUtil.getTime(time)) && startTime.before(DateUtil.getTime(time))) {
                flag = true;
                break;
            }
        }
        if (timeList.size() == 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 生成报警消息
     *
     * @param alarmMessageParam
     */
    private void generateMessage(AlarmMessageParam alarmMessageParam) {
        logger.info("生成报警消息,alarmMessageParam:{}", alarmMessageParam.toString());
        //查看消息接收人,生产报警消息
        Integer ruleId = alarmMessageParam.getRuleId();
        List<Integer> channelList = appMachWarnRuleChannelMapper.selectByRuleId(ruleId);
        if (channelList.size() <= 0) {
            return;
        }
        List<AppMsgToUserDTO> appWarnUserDTOS = appMachWarnRuleUserMapper.selectByRuleId(ruleId);
        if (appWarnUserDTOS.size() <= 0) {
            return;
        }
        PushMsgDTO pushMsgDTO = new PushMsgDTO();
        pushMsgDTO.setDeptId(alarmMessageParam.getDeptId());
        pushMsgDTO.setTitle(alarmMessageParam.getTitle());
        pushMsgDTO.setContent(alarmMessageParam.getContent());
        pushMsgDTO.setModuleType(alarmMessageParam.getModuleType());
        pushMsgDTO.setMsgObjectId(alarmMessageParam.getAlarmId());
        pushMsgDTO.setMsgChannelList(channelList);
        pushMsgDTO.setToUserList(appWarnUserDTOS);
        pushMsgDTO.setTime(alarmMessageParam.getTime());
        pushMsgDTO.setTriggerObjectId(alarmMessageParam.getTriggerObjectId());
        pushMsgDTO.setRuleType(alarmMessageParam.getRuleType());
        try {
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(pushMsgDTO));
        } catch (Exception ex) {
            logger.error("", ex);
        }
    }


}
